package tpenchere.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.omg.CORBA.ORB;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import tpenchere.client.Client;
import tpenchere.dao.impl.EnchereDAO;
import tpenchere.model.Categorie;
import tpenchere.model.Enchere;
import tpenchere.model.Produit;
import tpenchere.model.User;

@Service("EnchereServiceImpl")
public class EnchereServiceImpl extends EnchereServicePOA {

	@Autowired
	EnchereDAO enchereDAOJpa;

	// contient les utilisateurs enregistr�s � l'id d'un produit
	Map<Integer, List<Client>> registre = new HashMap<Integer, List<Client>>();
	
	// Map for specific push channel subscription
	Map<String, List<Client>> pushChannels = new HashMap<String, List<Client>>();
	
	/**
	 * Notify the client of an event on a channel
	 * @param channel
	 */
	private void pushNotify(String channel) {
		if(!pushChannels.containsKey(channel)) {
			// do nothing
			return;
		}
		List<Client> clients = pushChannels.get(channel);
		if(clients != null) {
			for(Client clt : clients) {
				System.out.println("Push for client in channel "+ channel);
				clt.pushChannel(channel);
			}
		}
	}

	private void fireEnchereModifie(Enchere enchere) {
		if (enchere.idProduit == 0) {
			throw new IllegalArgumentException("idProduit == 0");
		}
		if (enchere.idEnchere == 0) {
			throw new IllegalArgumentException("idEnchere == 0");
		}

		List<Client> clients = registre.get(enchere.idProduit);
		if (clients != null) {
			for (Client clt : clients) {
				clt.push(enchere);
			}
		}

	}
	
	public void registerFor(Client user, Produit produit) {
		if (registre.containsKey(produit.idProduit)) {
			registre.get(produit.idProduit).add(user);
		} else {
			//Vector is synchronized.
			List<Client> newList = new Vector<Client>();
			newList.add(user);
			registre.put(produit.idProduit, newList);
		}
	}
	
	/**
	 * Subscribe a client to a push channel
	 * @param channel
	 */
	public void subscribe(Client client, String channel) {
		if(pushChannels.containsKey(channel)) {
			System.out.println("new subscription on channel "+channel);
			pushChannels.get(channel).add(client);			
		} else {
			System.out.println("Create channel "+channel);
			List<Client> newList = new ArrayList<Client>();
			newList.add(client);
			pushChannels.put(channel, newList);
		}
	}

	public EnchereDAO getEnchereDAOJpa() {
		return enchereDAOJpa;
	}

	public void setEnchereDAOJpa(EnchereDAO enchereDAOJpa) {
		this.enchereDAOJpa = enchereDAOJpa;
	}

	public User connect(String login, String password) {

		return enchereDAOJpa.connect(login, password);
	}

	public Enchere saveEnchere(Enchere enchere) {
		Produit p = enchereDAOJpa.getProduit(enchere.idProduit);
		if(p.prixImmediat >= enchere.prix) {
			throw new IllegalArgumentException("Price below current bid !");
		}
		p.prixImmediat = enchere.prix;
		enchereDAOJpa.createProduit(p);
		Enchere e = enchereDAOJpa.createEnchere(enchere);
		//fireEnchereModifie(e);
		pushNotify("productList");
		return e;
	}

	public Produit createProduit(Produit produit) {
		Produit p = enchereDAOJpa.createProduit(produit);
		pushNotify("productList");
		return p;
	}

	public User createUser(User user) {
		return enchereDAOJpa.createUser(user);
	}

	public Produit[] getAllProduct() {
		return enchereDAOJpa.getAllProduct().toArray(new Produit[0]);
	}

	public Categorie[] getAllRootCategorie() {
		return enchereDAOJpa.getAllRootCategorie().toArray(new Categorie[0]);
	}
	
	public Categorie createCategorie(Categorie categorie) {
		pushNotify("category");
		return enchereDAOJpa.createCategorie(categorie);
	}

	public Produit[] getCurrentProduct() {
		return enchereDAOJpa.getCurrentProduct().toArray(new Produit[0]);
	}

	public Produit[] getProductBy(Categorie categorie) {
		return enchereDAOJpa.getProductBy(categorie).toArray(new Produit[0]);
	}

	public Produit[] getProductSold() {
		return enchereDAOJpa.getProductSold().toArray(new Produit[0]);
	}

	public boolean loginUsed(String login) {
		return enchereDAOJpa.loginUsed(login);
	}

	public Enchere getEnchere(Enchere enchere) {
		return enchereDAOJpa.getEnchere(enchere);
	}

	public Enchere[] getEnchereFor(Produit produit) {
		return enchereDAOJpa.getEnchere(produit).toArray(new Enchere[0]);
	}

	public void shutdown() {
		orb.shutdown(false);

	}

	ORB orb;

	public void setORB(ORB _orb) {
		orb = _orb;

	}

}
